import static org.junit.Assert.assertEquals;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;

import org.junit.Test;


public class LogicTest {

	Logic logic = new Logic();
	Task t1 = new Task();
	Task t2 = new Task();
	Task t3 = new Task();
	Task t4 = new Task();
	
	@Test
	public void test() throws ParseException, TaskNotFoundException, NotUniqueException {
		testTaskCompareTo();
		testSort();
		testFindIDByTitle();
		testFilterTasks();
		testFindTasksByKeyword();
	}

	private void testTaskCompareTo() throws ParseException {
		Task t1 = new Task();
		t1.id = 3;
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		
		Task t2 = new Task();
		t2.id = 4;
		t2.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t2.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		//all times not null, equal times
		assertEquals("tasks should be equal", 0, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t2.endTime = null;
		//one end time null, equal start times
		assertEquals("tasks should be equal", 0, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 10:00");
		t2.endTime = null;
		//one end time null, t1 before t2
		assertEquals("t2 starts after t1", -1, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = null;
		t2.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		//start time null, end times equal
		assertEquals("t2 ends after t1", -1, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 06:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t2.endTime = null;
		//end time null, start time in between
		assertEquals("t2 starts after t1", -1, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = null;
		t2.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 11:00");
		//end time after
		assertEquals("t2 starts after t1", -1, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = null;
		t2.endTime = null;
		//unscheduled task
		assertEquals("t2 not scheduled", -1, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 07:00");
		t1.endTime = null;
		t2.startTime = null;
		t2.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		//two nulls, start time after end time
		assertEquals("t2 ends after t1 starts", -1, t1.compareTo(t2), -1);
		
		t1.startTime = null;
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		t2.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t2.endTime = null;
		//two nulls, end time after start time
		assertEquals("t1 due before end of t2", 1, t1.compareTo(t2));
		
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 10:00");
		t1.endTime = null;
		t2.startTime = null;
		t2.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 09:00");
		//two nulls, end time after start time
		assertEquals("t1 starts after t2 ends", 1, t1.compareTo(t2));
		
		t1.startTime = null;
		t1.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 11:00");
		t2.startTime = null;
		t2.endTime = null;
		//three nulls
		assertEquals("t1 ends after t2", -1, t1.compareTo(t2));
		
		t1.startTime = null;
		t1.endTime = null;
		t2.startTime = null;
		t2.endTime = null;
		// all null
		assertEquals("both unscheduled", 0, t1.compareTo(t2));
		
	}
	
	@SuppressWarnings("deprecation")
	private void testSort() throws ParseException {
		t1.id = 35;
		t1.title = "meeting";
		t1.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 08:00");
		t1.endTime = null;
		t1.place = "meeting room";
		
		t2.id = 28;
		t2.title = "email bob";
		t2.startTime = null;
		t2.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 13:00");
		
		t3.id = 6;
		t3.title = "lunch";
		t3.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 11:00");
		t3.endTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 12:00");
		
		t4.id = 18;
		t4.title = "dont do this";
		t4.startTime = null;
		t4.endTime = null;
		
		logic.loadedData = new ArrayList<Task>();
		logic.loadedData.add(t3);
		logic.loadedData.add(t2);
		logic.loadedData.add(t4);
		logic.loadedData.add(t1);
		
		ArrayList<Task> sortedtasks = new ArrayList<Task>();
		sortedtasks.add(t1);
		sortedtasks.add(t3);
		sortedtasks.add(t2);
		sortedtasks.add(t4);
		
		Collections.sort(logic.loadedData);
		
		assertEquals("tasks not sorted", sortedtasks.toArray(), logic.loadedData.toArray());
	}
	
	private void testFindIDByTitle() throws TaskNotFoundException, NotUniqueException {
		assertEquals("find id by title", 1, logic.findIndexByTitle("lunch"));
		assertEquals("find id by title", 3, logic.findIndexByTitle("dont do this"));
		assertEquals("find id by title", 2, logic.findIndexByTitle("Email Bob"));
		assertEquals("find id by title", 0, logic.findIndexByTitle("meeting"));
		assertEquals("find id by title", -1, logic.findIndexByTitle("garbage"));
	}
	
	private void testFilterTasks() throws ParseException {
		ArrayList<Task> resultTasks = new ArrayList<Task>();
		Task filter = new Task();
		filter.place = "meeting";
		resultTasks.add(t1);
		
		assertEquals("filter tasks by place", resultTasks.toArray(), logic.filterTasks(filter).toArray());
		
		resultTasks.clear();
		
		filter.place = Task.EMPTY_STRING;
		filter.startTime = new SimpleDateFormat("dd/MM/yyyy HH:mm").parse("24/03/2013 10:00");
		resultTasks.add(t3);
		resultTasks.add(t2);
		assertEquals("filter tasks by time", resultTasks.toArray(), logic.filterTasks(filter).toArray());
		
		resultTasks.clear();
		filter.startTime = Task.EMPTY_TIME;
		filter.title = "email";
		resultTasks.add(t2);
		assertEquals("filter tasks by title", resultTasks.toArray(), logic.filterTasks(filter).toArray());
	}
	
	private void testFindTasksByKeyword() throws TaskNotFoundException {
		ArrayList<Task> resultTasks = new ArrayList<Task>();
		resultTasks.add(t1);
		resultTasks.add(t2);
		assertEquals("filter tasks by keyword", resultTasks.toArray(), logic.findTasksByKeyword("m").toArray());
		
		resultTasks.clear();
		resultTasks.add(t3);
		assertEquals("filter tasks by keyword", resultTasks.toArray(), logic.findTasksByKeyword("lunch").toArray());
		
		try {
			logic.findTasksByKeyword("garbage");
		} catch (TaskNotFoundException e) {
			assertEquals("filter tasks by keyword", true, true);
		}
	}

}
